﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PublicClass
{

    public class SetBlkByPathJig : DrawJig
    {
        private List<Entity> mListEnt = new List<Entity>();
        public double Dev { get; set; }
        private ObjectId BlkSample { get; set; }
        private ObjectId PathCurve { get; set; }
        private Point3d mDragPt = Point3d.Origin;

        /// <summary>
        /// 提示信息
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// 关键字列表
        /// </summary>
        public string KeyWordList { get; set; }
        /// <summary>
        /// 用户输入的关键字
        /// </summary>
        public string KeyWordUserInput { get; set; }

        /// <summary>
        /// 用户指定的点
        /// </summary>
        public Point3d DragPt
        {
            get
            { return mDragPt; }
            set
            {
                if (value == null)
                    return;
                else
                {
                    mDragPt = value;
                    UpDataDraw();
                }
            }
        }

        private BlockReference mBlk = null;
        private Curve mPathCurve = null;
        public SetBlkByPathJig()
        {
            Dev = 10;
            Prompt = "指定标注位置";
            KeyWordList = "";
            KeyWordUserInput = "";
            DragPt = Point3d.Origin;
        }
        private void Init()
        {

        }

        public static bool Do()
        {

            // 选择图块
            PromptEntityOptions opt = new PromptEntityOptions("\n选择样例图块");
            opt.SetRejectMessage("请选择图块");
            opt.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult res = CadUnits.CurEdit().GetEntity(opt);
            if (res.Status != PromptStatus.OK)
            {
                return false;
            }

            SetBlkByPathJig BlkPathJig = new SetBlkByPathJig();
            BlkPathJig.KeyWordList = "D";
            BlkPathJig.Prompt = "\n预览看效果或[设置密度系数(D)]";
            BlkPathJig.BlkSample = res.ObjectId;

            // 选择路径曲线
            opt = new PromptEntityOptions("\n选择路径曲线");
            opt.SetRejectMessage("请选择曲线");
            opt.AddAllowedClass(typeof(Curve), false);
            res = CadUnits.CurEdit().GetEntity(opt);
            if (res.Status != PromptStatus.OK)
            {
                return false;
            }

            BlkPathJig.PathCurve = res.ObjectId;

            while (true)
            {
                PromptResult resDrag = CadUnits.CurEdit().Drag(BlkPathJig);
                if (resDrag.Status == PromptStatus.OK)
                {
                    // 加入数据库
                    BlkPathJig.AddToDb();
                    break;
                }
                else if (resDrag.Status == PromptStatus.Keyword)
                {
                    PromptDoubleResult resDouble = CadUnits.CurEdit().GetDouble($"\n输入密度系数<{BlkPathJig.Dev}>:");
                    BlkPathJig.Dev = resDouble.Value;
                    BlkPathJig.UpDataDraw();
                    continue;
                }
                else
                    return false;
            }
            return true;
        }

        void UpDataDraw()
        {
            if (null == mBlk || null == mPathCurve)
            {
                if (BlkSample.IsNull || PathCurve.IsNull)
                    return;

                using (Transaction ts = CadUnits.StartTransaction())
                {
                    DBObject objSample = ts.GetObject(BlkSample, OpenMode.ForRead);
                    if (null != objSample)
                        mBlk = objSample as BlockReference;

                    DBObject objPath = ts.GetObject(PathCurve, OpenMode.ForRead);
                    if (null != objPath)
                        mPathCurve = objPath as Curve;
                }
            }

            mListEnt.Clear();

            double dS = mPathCurve.GetDistanceAtParameter(mPathCurve.StartParam);
            double dLength = mPathCurve.GetDistanceAtParameter(mPathCurve.EndParam);
            double dSep = Dev;
            double dForLength = dLength / dSep;

            Point3d ptS = mPathCurve.GetPointAtDist(dS);
            Vector3d vecS = mPathCurve.GetFirstDerivative(ptS);

            Vector3d vecDrag = DragPt - ptS;
            bool bMirror = false;
            double dZ = vecDrag.CrossProduct(vecS).Z;
            if (dZ > 0)
            {
                bMirror = true;
            }

            for (dS = 0; dS <= dLength; dS += dForLength)
            {
                Point3d pt = mPathCurve.GetPointAtDist(dS);
                Vector3d vec = mPathCurve.GetFirstDerivative(pt);

                BlockReference blkFor = mBlk.Clone() as BlockReference;

                blkFor.Position = pt;
                blkFor.Rotation = vec.GetAngleTo(Vector3d.XAxis, -Vector3d.ZAxis);
                if (bMirror)
                    blkFor.Rotation = blkFor.Rotation + Math.PI;
                mListEnt.Add(blkFor);
            }
        }

        /// <summary>
        /// 所有实体加入数据库
        /// </summary>
        public void AddToDb()
        {
            using (Transaction ts = CadUnits.StartTransaction())
            {
                foreach (var item in mListEnt)
                {
                    CadUnits.AppendEntity(ts, item);
                }

                ts.Commit();
            }
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptPointOptions jigPrompt = null;
            // 区分有关键字和没有关键字 注意 和 [] 对应起来,否则报异常
            if (null != KeyWordList && KeyWordList.Length > 0)
            {
                jigPrompt = new JigPromptPointOptions(Prompt, KeyWordList);
            }
            else
                jigPrompt = new JigPromptPointOptions(Prompt);

            jigPrompt.UserInputControls = UserInputControls.GovernedByOrthoMode | UserInputControls.NullResponseAccepted | UserInputControls.DoNotEchoCancelForCtrlC;

            // setUserInputControls((UserInputControls)(kGovernedByOrthoMode | kNullResponseAccepted | kDontEchoCancelForCtrlC));

            PromptPointResult res = prompts.AcquirePoint(jigPrompt);

            KeyWordUserInput = res.StringResult;

            if (res.Status != PromptStatus.OK)
                return SamplerStatus.NoChange;

            Point3d ptLast = DragPt;

            if (ptLast.IsEqualTo(res.Value))
                return SamplerStatus.NoChange;

            // 更新标注
            DragPt = res.Value;

            return SamplerStatus.OK;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            if (null != mPathCurve)
            {
                double dS = mPathCurve.GetDistanceAtParameter(mPathCurve.StartParam);
                Point3d pt = mPathCurve.GetPointAtDist(dS);

                Line line = new Line();
                line.StartPoint = pt;
                line.EndPoint = DragPt;

                line.WorldDraw(draw);
            }

            // 绘制
            foreach (var item in mListEnt)
            {
                item.WorldDraw(draw);
            }

            return true;
        }
    }
}
